<!DOCTYPE html>
<html lang="en" style="height: 100%">

<head>
  <script src="./react.development.js"></script>
  <script src="./react-dom.development.js"></script>
  <script src="./babel.min.js"></script>
</head>
<style>
  .list {
    width: 500px;
  }

  .item {
    background: #eee;
  }

  .footer {
    display: flex;
  }

  .fl {
    display: flex;
    justify-content: space-between;
  }
</style>

<body style="height: 100%">
  <div id="root" style="height: 100%"></div>
  <script type="text/babel">
    /***
       *
       *
       *   笔试题共4题,根据自身情况选择完成(60分钟以内)
       *
       *
       * */

    /**
     * 完善 下方 findAllParentDepts 函数 , 返回 某个id 的所有的上层节点的id数组
     * 如  'U2dPWLOxD-Gh7lqt4mw2Z'   =>   ['3E2X3qZA0db3lonc5h_Xs','WSOslzzUg-OfyPGGVidqi']
     * */
    let deptTree = [
      {
        id: "WSOslzzUg-OfyPGGVidqi",
        title: "擎创科技",
        children: [
          {
            id: "3E2X3qZA0db3lonc5h_Xs",
            title: "产品一部",
            children: [
              {
                id: "U2dPWLOxD-Gh7lqt4mw2Z",
                title: "一部测试组",
                children: [
                  {
                    id: "OcbCKlsNwa1yV4hV4kl2q",
                    title: "测试一组",
                    children: [
                      {
                        id: "QjNB3D_iZPA0UuPkeKKFx",
                        title: "王凯",
                      },
                      {
                        id: "eTcPMpVqHPqWeov1mOP5Q",
                        title: "王龙",
                      },
                    ],
                  },
                ],
              },
              {
                id: "OU3V1152OtmgWf4_pO8dT",
                title: "一部设计部",
                children: [
                  {
                    id: "BGE-fSUdl7WxYLCV4PwoV",
                    title: "小李",
                  },
                  {
                    id: "wPd-EoVwD9y96IMXEazne",
                    title: "小张",
                  },
                  {
                    id: "uimLbEVgrtHgq8B_UoLZj",
                    title: "小王",
                  },
                ],
              },
            ],
          },
          {
            id: "41ngVYWBCRpcrzPaaFyp3",
            title: "产品二部",
          },
        ],
      },
    ];
    /**
     * @param {Array} data  部门树
     * @param {string} id   部门树中某个节点id
     * @returns {Array<string>}     所有的上层节点的id数组
     */
    function findAllParentDepts (data, id) {
      let result = [];

      // 添加父级id的方法
      const addParentId = (arr1, pId = "-1") => {
        return arr1.map((item) => {
          if (item.children) {
            item.children = addParentId(item.children, item.id);
          }
          return {
            ...item,
            parentId: pId,
          };
        });
      };

      // 添加父级节点
      const arrTemp = addParentId(data);

      // 查找上层节点的数组方法
      const findParentIds = (arr2, id2, res = []) => {
        arr2.forEach((e) => {
          if (e.id === id2 && e.parentId !== "-1") {
            // 最外层不进行查找
            res.unshift(e.parentId);
            findParentIds(arrTemp, e.parentId, res); // 从最后一级找到父级,继续传入全部的树数组          
          } else {
            if (e.children) {
              findParentIds(e.children, id2, res);
            }
          }
        });
        return res;
      };

      result = findParentIds(arrTemp, id);
      return result;
    }
    console.log(
      "🚀  findAllParentDepts 测试结果:",
      findAllParentDepts(deptTree, "OcbCKlsNwa1yV4hV4kl2q")
    );

    /**
     *  2、完善下方 TODOList 组件 , 参照图为当前文件夹中 “todolilst组件参照图.png”
     *  该组件功能为： 添加item (上方输入框输入后,点击submit添加) /  删除item(点击 “ X ” 删除) / 完成item(勾选前方checkbox即为完成)
     *  左下角显示剩余多少item未完成 , 右下角 点击筛选状态 (所有item / 已完成item)
     *
     ******************************************** */
    const { useState, useEffect } = React;
    function TodoList () {
      //your code
      // 计划列表
      const [todoList, setTodoList] = useState([]);
      // 输入框的值
      const [inputVal, setInputVal] = useState("");
      // 是否展示全部
      const [showAll, setShowAll] = useState(true);

      // 提交计划的方法
      const onSubmit = () => {
        console.log('点击了')
        if (inputVal) {
          setTodoList([
            ...todoList,
            {
              id: Date.now(),
              value: inputVal,
              done: false,
              time: Date.now(),// 更新时间
            },
          ]);
          setInputVal("")
          setShowAll(true)
        }
      }

      // 选中方法
      const onCheckChang = (checked, id) => {
        console.log('选中了')
        setTodoList(
          todoList.map((item) => {
            if (item.id === id) {
              item.done = checked;
              item.time = Date.now();// 更新时间
            }
            return item;
          })
        );
      }

      // 删除某一项方法
      const onDelete = (id) => {
        setTodoList(
          todoList.filter((item) => {
            return item.id !== id;
          })
        );
      }

      // Item 组件
      const Item = (props) => {
        console.log('props', props);
        const { value, done, id } = props;
        return (
          <div className='item fl'>
            <div>
              <input checked={done} type="checkbox" name="" id="" onChange={(e) => { onCheckChang(e.target.checked, id) }} />
              <span style={{ textDecoration: done ? 'line-through' : '' }}>{value}</span>
            </div>
            <div onClick={() => { onDelete(id) }}>x</div>
          </div>
        )
      }

      // 为完成列表
      const completedList = todoList.filter(item => item.done).sort((a, b) => b.time - a.time)
      // 未完成列表
      const unCompletedList = todoList.filter(item => !item.done).sort((a, b) => b.time - a.time)
      // 全部列表 用时间来排序
      const tempTodoList = todoList.sort((a, b) => b.time - a.time)
      return (
        <div className="list">
          <div style={{ marginTop: 8 }}>
            <input type="text" placeholder="Add new todo..." value={inputVal} onChange={(e) => { setInputVal(e.target.value.trim()) }} />
            <button onClick={onSubmit}>Submit</button>
          </div>
          <div>
            {
              showAll && (
                <div>
                  {unCompletedList.map(item => (<Item {...item} key={item.id} />))}
                </div>
              )
            }
            {completedList.map(item => (<Item {...item} key={item.id} />))}
          </div>
          <div className='footer fl'>
            <div>{todoList.length - completedList.length}item left</div>
            <div>
              <span style={{ background: showAll ? 'red' : '' }} onClick={() => { setShowAll(true) }}>All</span>
              <span style={{ marginLeft: 10, background: showAll ? '' : 'red' }} onClick={() => { setShowAll(false) }}>Completed</span>
            </div>
          </div>
        </div>
      );
    }
    function Page () {
      return <TodoList />;
    }
    ReactDOM.render(<Page />, document.getElementById("root"));

    /**
     * 3、完善deleteVirtualWrapper函数 , 将obj对象中的虚拟包裹层(isVirtualWrapper === true的对象)删除 (将该对象的其余属性放置到上一层对象中, 如果上一层对象任然为虚拟包裹层 , 则继续放置到上一层对象)
     * ex: {
     *        name:'tom',
     *        virtualY:{
     *                   isVirtualWrapper:true,
     *                   companyName:'擎创科技',
     *                   location:'上海'
     *                },
     *        virtualA:{
     *                   isVirtualWrapper:true,
     *                   virtualB:{
     *                              isVirtualWrapper:true,
     *                              address:'孵化园C区'
     *                            },
     *                   realProp:{  isVirtualWrapper:false, title:'真实属性' }
     *                 }
     *    }
     *
     * ==> { name:'tom', companyName:'擎创科技', location:'上海' , address:'孵化园C区' ,  realProp:{ isVirtualWrapper:false, title:'真实属性' }  }
     *
     */
    let obj = {
      name: "tom",
      virtualY: {
        isVirtualWrapper: true,
        companyName: "擎创科技",
        location: "上海",
      },
      virtualA: {
        isVirtualWrapper: true,
        virtualB: { isVirtualWrapper: true, address: "孵化园C区" },
        realProp: { isVirtualWrapper: false, title: "真实属性" },
      },
    };
    /**
     * @param {Object} data  需要剔除虚拟层的源数据
     * @returns {Object}     剔除虚拟层后的数据
     */
    function deleteVirtualWrapper (data) {
      //your code
      const map = {};
      // 遍历对象属性
      const getObject = (obj) => {
        if (typeof obj === "object") {
          const keys = Object.keys(obj);
          keys.forEach((key) => {
            if (key !== "isVirtualWrapper") {
              if (obj[key].isVirtualWrapper) {
                // 如果是虚拟包裹层
                const temp = obj[key];
                delete obj[key];
                getObject(temp);
              } else {
                // 如果不是虚拟包裹层
                map[key] = obj[key];
              }
            }
          });
        }
      };
      getObject(data);
      return map;
    }
    console.log(
      "🚀  deleteVirtualWrapper 测试结果:",
      deleteVirtualWrapper(obj)
    );

    /**
     * 4、进入当前文件夹中的“原型面试题” , 查看 “视图.html”  , 理解该原型 , 并写出你认为完成此模块需要后端提供多少个接口并简要描述, 示例如下
     * ex :  ① getUserInfo接口
     *            参数: userId (用户id)
     *            返回结果:  { "userName":"JACK" , "gender":"male" , "age":49 }
     *       ② getUserList接口
     *            参数:deptId(部门id) /  size(页大小) / pageNum(页码)
     *            返回结果:  { "total":66, "pageNum":1,"size":10, "resords":[] }
     *
     *     //your answer
     *    1.视图页面
     *      (1) getViewList 获取视图列表接口
     *            参数:无
     *            返回结果:  { "code":0,"msg":"success","data":[{"id":1,"name":"视图1"},{"id":2,"name":"视图2"}] }
     *      (2) getViewInfoList 获取视图信息接口
     *            参数: {id:1,pageIndex:1,pageSize:10}(视图id,分页参数)
     *            返回结果:{ "code":0,
     *                      "msg":"success",
     *                      "data":{
     *                            "total":66, 
     *                            "pageNum":1,
     *                            "size":10,
     *                            "resords": [{"id":1,"name":"指标","attrList":[{"code":'attr1',"name":'属性1'...}]}],
     *                             }
     *      (3) export 导出接口
     *            参数: {keyword:'搜索关键词'}
     *            返回结果:blob格式文件流
     *      (4) deleteViewById 删除视图接口
     *            参数: {id:1}(视图id)
     *            返回结果:{ "code":0,"msg":"success"}
     *    2.模型模块
     *      (1) getModelList 查询模型树
     *            参数:{catalogId:1}(目录id)
     *          返回结果:  { "code":0,"msg":"success","data":
     *                        [{"id":1,"name":"层级1","chilren":[{"id":1,"name":"指标","attrList":[{"code":'attr1',"name":'属性1'...}]}]}] }
     *      (2)CI模型的查询条件列表接口
     *      (3)CI模型查询条件增删查改接口
     *      (4)整个视图的保存接口
     * */
  </script>
</body>

</html>